<template>
  <div class="group-rules" v-loading="isLoadingDetail">
    <div class="group-rules__button">
      <span>筛选条件</span>
      <el-button type="primary" link :icon="Plus" @click="handelAddGroup">添加筛选条件</el-button>
    </div>
    <div class="group-rules__list">
      <div
        class="group-rules__item"
        v-for="(item, conditionsIndex) in conditions.conditionGroupList ?? []"
        v-loading="isGroupLoading"
      >
        <!--      start 条件关系符  -->
        <div class="group-not-type" v-if="conditionsIndex === 0">当</div>
        <el-select v-else class="group-type" placeholder="" v-model="item.compare">
          <el-option label="且" value="and"></el-option>
          <el-option label="或" value="or"></el-option>
        </el-select>
        <div class="horizontal-line"></div>
        <div class="branch-line" :style="{ height: `${item.conditionList?.length * 43}px` }"></div>
        <!--  end  条件关系符-->

        <!--      start 条件列表  -->
        <div class="conditions-list">
          <div class="conditions-list__item" v-for="(subItem, subIndex) in item.conditionList ?? []" :key="subItem.id">
            <!-- 表单字段 start -->
            <el-select
              class="form-field"
              :class="{ 'form-field-err': subItem.isErr }"
              :disabled="isDisabledFieldOption(subItem).value"
              placeholder="请选择"
              filterable
              v-model="subItem.id"
              @change="changeField($event, subIndex, item.conditionList)"
            >
              <el-option
                v-for="fieldItem in fieldsList ?? []"
                :key="fieldItem.id"
                :label="fieldItem.title"
                :value="fieldItem.id"
              ></el-option>
            </el-select>
            <!-- 表单字段 end -->
            <!--条件关系 start -->
            <el-select
              class="condition-filter"
              :class="{ 'form-field-err': subItem.isErr }"
              placeholder="请先选择字段"
              v-model="subItem.compare"
              :disabled="isDisabledConditionOption(subItem).value"
              @change="initFilter(subItem)"
            >
              <el-option
                v-for="(typeItem, index) in subItem.condition ?? []"
                :key="`${typeItem.value}${index}`"
                :label="typeItem.label"
                :value="typeItem.value"
              ></el-option>
            </el-select>
            <!--条件关系  end -->

            <!-- 条件组件 start -->
            <div>
              <!--    number   -->
              <template v-if="subItem.option?.type === 'NumberInput'">
                <div :class="{ 'form-field-err': subItem.isErr }">
                  <el-input
                    v-if="inputCompare.includes(subItem.compare)"
                    style="width: 225px"
                    type="number"
                    v-model.number="subItem.value[0]"
                    placeholder="请输入"
                    clearable
                  />
                  <template v-if="rangeCompare.includes(subItem.compare)">
                    <el-input
                      type="number"
                      style="width: 200px"
                      v-model.number="subItem.value[0]"
                      placeholder="请输入"
                      clearable
                    />
                    <el-input
                      type="number"
                      style="width: 200px"
                      v-model.number="subItem.value[1]"
                      placeholder="请输入"
                      clearable
                    />
                  </template>
                </div>
              </template>

              <!--     string   -->
              <template v-if="subItem.option?.type === 'TextInput'">
                <div :class="{ 'form-field-err': subItem.isErr }">
                  <el-input
                    style="width: 234px"
                    v-if="textCompare.includes(subItem.compare)"
                    v-model="subItem.value[0]"
                    placeholder="请输入"
                    clearable
                  />
                  <el-select
                    style="width: 234px"
                    v-if="textCompareRange.includes(subItem.compare)"
                    multiple
                    filterable
                    allow-create
                    default-first-option
                    collapse-tags-tooltip
                    :reserve-keyword="false"
                    collapse-tags
                    :max-collapse-tags="1"
                    v-model="subItem.value"
                  >
                    <el-option
                      v-for="(textItem, textIndex) in subItem.value"
                      :key="`${textItem.value}-${textIndex}`"
                      :label="textItem"
                      :value="textItem"
                    ></el-option>
                  </el-select>
                </div>
              </template>

              <!--     date   -->
              <template v-if="subItem.option?.type === 'SelectDate'">
                <div :class="{ 'form-field-err': subItem.isErr }">
                  <el-date-picker
                    v-if="subItem.compare !== 'Between'"
                    style="width: 234px"
                    v-model="subItem.value[0]"
                    type="date"
                    value-format="YYYY-MM-DD"
                    format="YYYY-MM-DD"
                    date-format="YYYY-MM-DD"
                    placeholder="请选择"
                  />
                  <el-date-picker
                    v-else
                    v-model="subItem.value"
                    type="daterange"
                    value-format="YYYY-MM-DD"
                    format="YYYY-MM-DD"
                    date-format="YYYY-MM-DD"
                    range-separator="—"
                    start-placeholder="开始时间"
                    end-placeholder="结束时间"
                  />
                  <el-select style="width: 234px" v-model="subItem.value[0]" v-if="subItem.compare === 'Dynamic'">
                    <el-option
                      v-for="(selectItem, selectIndex) in dynamicOptions"
                      :key="`${selectItem.value}-${selectIndex}`"
                      :label="selectItem.label"
                      :value="selectItem.value"
                    ></el-option>
                  </el-select>
                </div>
              </template>

              <!--     select   -->
              <template v-if="subItem.option?.type === 'SelectInput'">
                <div :class="{ 'form-field-err': subItem.isErr }">
                  <el-select
                    style="width: 234px"
                    v-model="subItem.value[0]"
                    :disabled="isDisabledSelect(subItem).value"
                    @change="changeSelectInput($event, subItem)"
                  >
                    <el-option
                      v-for="(selectItem, selectIndex) in subItem.option?.data ?? []"
                      :disabled="isDisabledSelect(subItem).value"
                      :key="`${selectItem.value}-${selectIndex}`"
                      :label="selectItem.label"
                      :value="selectItem.value"
                    ></el-option>
                  </el-select>
                </div>
              </template>

              <!--     MultipleSelect   -->
              <template v-if="subItem.option?.type === 'MultipleSelect'">
                <div :class="{ 'form-field-err': subItem.isErr }">
                  <el-select
                    style="width: 234px"
                    multiple
                    v-model="subItem.value"
                    :disabled="isDisabledSelect(subItem).value"
                    allow-create
                    default-first-option
                    collapse-tags-tooltip
                    :reserve-keyword="false"
                    collapse-tags
                    :max-collapse-tags="1"
                  >
                    <el-option
                      v-for="(selectItem, selectIndex) in subItem.option?.data ?? []"
                      :key="`${selectItem.value}-${selectIndex}`"
                      :label="selectItem.label"
                      :value="selectItem.value"
                    ></el-option>
                  </el-select>
                </div>
              </template>

              <!--    CascaderInput    -->
              <template v-if="subItem.option.type === 'CascaderInput'">
                <div :class="{ 'form-field-err': subItem.isErr }">
                  <el-cascader
                    style="width: 234px"
                    v-model="subItem.value"
                    clearable
                    :props="{
                      label: 'name',
                      value: 'cityCode'
                    }"
                    :options="addressOptions"
                  ></el-cascader>
                </div>
              </template>
            </div>
            <!--     条件组件 end   -->
            <svg-icon
              icon-class="del"
              class-name="del-icon"
              v-if="isShowDelIcon(item).value"
              @click="handelDelCondition(item, subIndex, conditionsIndex)"
            />
          </div>
          <el-button type="info" color="#F2F3F5" :icon="Plus" @click="handelAddCondition(item)"></el-button>
        </div>
        <!--      end 条件列表  -->
      </div>
    </div>
  </div>
</template>

<script setup>
import { computed, getCurrentInstance, ref } from "vue";
import { Plus } from "@element-plus/icons-vue";
import { cloneDeep } from "lodash";
import { portraitList } from "@/apis/dict/dict";
import { getAllListByType, getRole } from "@/apis/system";
import { departmentTree } from "@/apis/user";
import { allConditionField } from "@/apis/groups";
import addressOptions from "@/assets/pca-code";
import { inputCompare, rangeCompare, textCompare, textCompareRange, dynamicOptions } from "./config";
import useComputedParams from "@/hooks/useComputedParams";

const props = defineProps({
  modelValue: {
    type: Array,
    default: () => []
  }
});
const emit = defineEmits(["update:modelValue"]);
const conditions = computed({
  get() {
    return props.modelValue;
  },
  set(val) {
    emit("update:modelValue", val);
  }
});

const { proxy } = getCurrentInstance();

const isDisabledFieldOption = useComputedParams(data => {
  if (fieldsList.value?.length && fieldsList.value.length === 1) {
    data.id = fieldsList.value[0].id;
    return true;
  }
  return false;
});
const isDisabledConditionOption = useComputedParams(data => {
  if (data.condition?.length && data.condition.length === 1) {
    data.compare = data.condition[0].value;
    return true;
  }
  return false;
});
const isDisabledSelect = useComputedParams(subItem => {
  const optionData = subItem.option?.data ?? [];
  if (optionData.length && optionData.length === 1) {
    subItem.value = [optionData[0].value];
    return true;
  }
  return false;
});
const isShowDelIcon = useComputedParams(item => {
  return conditions.value.conditionGroupList?.length > 1 || item.conditionList?.length > 1;
});

/**
 * 规则
 */
const isLoadingDetail = ref(false);
const fieldsList = ref([]);
const getAllConditionField = async () => {
  try {
    const { data } = await allConditionField();
    fieldsList.value = data ?? [];
  } catch (err) {
    console.log(err);
  }
};

const isGroupLoading = ref(false);

/**
 * 业务类型
 */
const getPortraitList = async () => {
  const { data } = await portraitList();
  return (
    data?.map(item => ({
      label: item.portraitName,
      value: item.portraitId
    })) || []
  );
};
/**
 * 角色
 */
const getRoleList = async () => {
  const { data } = await getRole();
  return (
    data?.map(item => ({
      label: item.roleName,
      value: item.roleId
    })) || []
  );
};
/**
 * 部门
 */
const deptList = nodes => {
  const list = [];
  const _fn = node => {
    const { id, deptName } = node;
    list.push({ value: id, label: deptName });
    if (node.children?.length) {
      node.children.forEach(child => _fn(child));
    }
  };
  nodes.forEach(node => _fn(node));
  return list;
};
const getDeptList = async () => {
  const { data } = await departmentTree();
  return deptList(data);
};
/**
 * 选择字段
 * @param e
 * @param subIndex -条件索引
 * @param subList -条件列表
 */
const sourceMap = new Map([
  ["portraitName", getPortraitList],
  ["principal_role_id", getRoleList],
  ["principal_dept_id", getDeptList]
]);
const changeField = async (e, subIndex, subList) => {
  const condition = fieldsList.value.find(item => item.id === e);
  subList[subIndex] = cloneDeep(condition);
  //  todo:可以优化数据结构，由接口统一返回
  if (condition.option?.lazy) {
    subList[subIndex].value = [];
    if ("check_ids" === condition.id) {
      const { data } = await getAllListByType({ type: "check" });
      subList[subIndex].option.data =
        data?.map(item => {
          return {
            label: item.labelName,
            value: item.id
          };
        }) ?? [];
      return;
    }
    if (sourceMap.has(condition.id)) {
      const getData = sourceMap.get(condition.id);
      subList[subIndex].option.data = await getData();
      return;
    }
    return proxy.$modal.msgError(`没有【${condition.title}】的数据`);
  }
};
/**
 * 选择条件
 * @param e
 * @param subItem
 */
const changeSelectInput = (e, subItem) => {
  const label = subItem.options?.find(item => item.value === e)?.label;
  subItem.label = label ? [label] : [];
};

/**
 * 添加条件组
 */
const handelAddGroup = () => {
  conditions.value.conditionGroupList ??= [];
  conditions.value.conditionGroupList.push({
    compare: "and",
    conditionList: [
      {
        id: "",
        title: "",
        condition: [],
        option: {
          type: "SelectInput",
          optionDataSource: {},
          data: []
        },
        compare: "",
        value: []
      }
    ]
  });
};
/**
 * 添加规则
 */
const handelAddCondition = item => {
  item.conditionList ??= [];
  item.conditionList.push({
    id: "",
    title: "",
    condition: [],
    option: {
      type: "SelectInput",
      optionDataSource: {},
      data: []
    },
    compare: "",
    value: []
  });
};
/**
 * 删除
 * @param item -当前条件
 * @param index -当前条件索引
 * @param conditionsIndex 当前规则索引
 */
const handelDelCondition = (item, index, conditionsIndex) => {
  if (item.conditionList?.length === 1) {
    return conditions.value.conditionGroupList?.splice(conditionsIndex, 1);
  }
  item.conditionList.splice(index, 1);
};

getAllConditionField();
</script>

<style scoped lang="scss">
@import "GroupRules";
</style>
